package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

    @Autowired
    private TrackInfoMapper trackInfoMapper;

    @Autowired
    private AlbumInfoMapper albumInfoMapper;

    @Autowired
    private VodService vodService;

    @Autowired
    private TrackStatMapper trackStatMapper;

    @Autowired
    private UserInfoFeignClient userInfoFeignClient;

    /**
     * 根据声音Id 查询声音列表
     *
     * @param trackId
     * @param trackCount 可能是0;
     * @return
     */
    @Override
    public List<TrackInfo> findPaidTrackInfoList(Long trackId, Integer trackCount) {
        //  创建集合对象
        List<TrackInfo> trackInfoList = new ArrayList<>();
        //  根据声音Id获取当前声音对象
        TrackInfo trackInfo = this.getById(trackId);
        //  1.  先获取到用户已购买的声音列表;
        Result<List<Long>> userPaidTrackList = userInfoFeignClient.findUserPaidTrackList(trackInfo.getAlbumId());
        Assert.notNull(userPaidTrackList, "用户已购买过声音结果集为空！");
        //  有可能是空，也有可能不是空！
        List<Long> list = userPaidTrackList.getData();
        //  2.  获取到从当前声音id开始，往后数n条记录!
        //  select * from track_info where order_num > 10 and album_id = 391 and id not in (20767,20768) and is_deleted = 0 limit  10;
        if (trackCount > 0) {
            //  使用mapper 生成sql 语句;
            //  构建查询条件
            LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TrackInfo::getAlbumId, trackInfo.getAlbumId()).gt(TrackInfo::getOrderNum, trackInfo.getOrderNum());
            //  判断用户是否已购买过声音!
            if (!CollectionUtils.isEmpty(list)) {
                //  有购买记录;
                wrapper.notIn(TrackInfo::getId, list);
            }
            //  限制购买集数
            wrapper.last(" limit " + trackCount);
            //  获取购买声音列表
            trackInfoList = trackInfoMapper.selectList(wrapper);
        } else {
            //  购买本集；
            trackInfoList.add(trackInfo);
        }
        //  返回数据;
        return trackInfoList;
    }

    @Override
    public List<Map<String, Object>> findUserTrackPaidList(Long trackId) {
        //  先查询需要付费的声音列表;
        //  根据声音Id 查询声音对象
        TrackInfo trackInfo = this.getById(trackId);
        //  获取专辑Id;  trackInfo.getAlbumId(); 获取专辑对象
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());

        //  select * from track_info where order_num > 6 and album_id = 391 and is_deleted = 0;
        LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TrackInfo::getAlbumId, albumInfo.getId()).gt(TrackInfo::getOrderNum, trackInfo.getOrderNum());
        //  点击当前声音时获取到的所有需要付费的声音列表!
        List<TrackInfo> trackInfoList = trackInfoMapper.selectList(wrapper);
        //  查询用户已购买过哪些声音; 6-54;49--> 除去购买过的！ 20,21,22,23,24 实际应该是44条声音需要付费！
        Result<List<Long>> userPaidTrackList = userInfoFeignClient.findUserPaidTrackList(albumInfo.getId());
        Assert.notNull(userPaidTrackList, "用户已购买过声音结果集为空！");
        List<Long> list = userPaidTrackList.getData();
        //  获取两个集合的差集:
        List<Long> trackIdAllPaidList = trackInfoList.stream().map(TrackInfo::getId).collect(Collectors.toList());
        List<Long> paidTrackIdList = trackIdAllPaidList.stream().filter(tId -> !list.contains(tId)).collect(Collectors.toList());
        //  构建一个集合列表;
        List<Map<String, Object>> listMap = new ArrayList<>();
        //  获取单条声音的价格;
        BigDecimal price = albumInfo.getPrice();
        //  构建返回结果;
        if (paidTrackIdList.size() >= 0) {
            //  显示本集；
            Map<String, Object> map = new HashMap<>();
            map.put("name", "本集");
            map.put("price", price);
            map.put("trackCount", 0);
            //  将map 添加到集合中
            listMap.add(map);

        }
        //  size() 属于1到10 之间;  9;
        if (paidTrackIdList.size() > 0 && paidTrackIdList.size() <= 10) {
            Map<String, Object> map = new HashMap<>();
            map.put("name", "后" + paidTrackIdList.size() + "集");
            map.put("price", price.multiply(new BigDecimal(String.valueOf(paidTrackIdList.size()))));
            map.put("trackCount", paidTrackIdList.size());
            //  将map 添加到集合中
            listMap.add(map);
        }
        //  size() 超过10 19 后10集;
        if (paidTrackIdList.size() > 10) {
            Map<String, Object> map = new HashMap<>();
            map.put("name", "后10集");
            map.put("price", price.multiply(new BigDecimal("10")));
            map.put("trackCount", 10);
            //  将map 添加到集合中
            listMap.add(map);
        }
        //  后19集;
        if (paidTrackIdList.size() > 10 && paidTrackIdList.size() <= 20) {
            Map<String, Object> map = new HashMap<>();
            map.put("name", "后" + paidTrackIdList.size() + "集");
            map.put("price", price.multiply(new BigDecimal(String.valueOf(paidTrackIdList.size()))));
            map.put("trackCount", paidTrackIdList.size());
            //  将map 添加到集合中
            listMap.add(map);
        }
        //  size() 超过10 19
        if (paidTrackIdList.size() > 20) {
            Map<String, Object> map = new HashMap<>();
            map.put("name", "后20集");
            map.put("price", price.multiply(new BigDecimal("20")));
            map.put("trackCount", 20);
            //  将map 添加到集合中
            listMap.add(map);
        }
        //  后29集;
        if (paidTrackIdList.size() > 20 && paidTrackIdList.size() <= 30) {
            Map<String, Object> map = new HashMap<>();
            map.put("name", "后" + paidTrackIdList.size() + "集");
            map.put("price", price.multiply(new BigDecimal(String.valueOf(paidTrackIdList.size()))));
            map.put("trackCount", paidTrackIdList.size());
            //  将map 添加到集合中
            listMap.add(map);
        }
        //  size()
        if (paidTrackIdList.size() > 30) {
            Map<String, Object> map = new HashMap<>();
            map.put("name", "后30集");
            map.put("price", price.multiply(new BigDecimal("30")));
            map.put("trackCount", 30);
            //  将map 添加到集合中
            listMap.add(map);
        }
        //  返回数据
        return listMap;
    }

    @Override
    @Transactional
    public void trackStatUpdate(TrackStatMqVo trackStatMqVo) {
        //  先更新声音的播放量;
        //  update track_stat set stat_num = stat_num + ? where track_id = ? and stat_type = ? and is_deleted = 0;
        trackStatMapper.trackStatUpdate(trackStatMqVo.getCount(), trackStatMqVo.getTrackId(), trackStatMqVo.getStatType());
        //  也需要更新专辑的播放量;
        if (SystemConstant.TRACK_STAT_PLAY.equals(trackStatMqVo.getStatType())) {
            //  更新专辑的;
            albumInfoMapper.albumStatUpdate(trackStatMqVo.getCount(), trackStatMqVo.getAlbumId(), SystemConstant.ALBUM_STAT_PLAY);
        }
    }

    @Override
    public IPage<AlbumTrackListVo> findAlbumTrackPage(Page<AlbumTrackListVo> trackListVoPage, Long albumId, Long userId) {
        //  1.  先根据专辑Id，与分页条件，查询出声音列表数据;
        IPage<AlbumTrackListVo> iPage = trackInfoMapper.selectAlbumTrackPage(trackListVoPage, albumId);
        //  根据专辑Id获取专辑对象;
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        //  2.  判断当前用户是否登录;
        if (null == userId) {
            //  未登录：专辑类型除免费之外，则除免费试听的声音之外，都需要付费！

            if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfo.getPayType())) {
                //  设置付费声音列表; select tracks_for_free from album_info where id = 383;  tracks_for_free:表示免费的试听集数;
                iPage.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree()).forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
            }
        } else {
            //  定义一个变量来存储是否需要付费标识;
            boolean isNeedPaidMark = false;
            //    用户已经登录;
            if (SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(albumInfo.getPayType())) {
                //  判断用户不是vip 或 是vip 但是vip 已经过期了;
                Result<UserInfoVo> infoVoResult = userInfoFeignClient.getUserInfo(userId);
                Assert.notNull(infoVoResult, "用户信息结果集不存在！");
                UserInfoVo userInfoVo = infoVoResult.getData();
                Assert.notNull(userInfoVo, "用户信息不存在！");
                if (0 == userInfoVo.getIsVip() || (1 == userInfoVo.getIsVip() && userInfoVo.getVipExpireTime().before(new Date()))) {
                    //  设置需要付费标识
                    isNeedPaidMark = true;
                }
            } else if (SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(albumInfo.getPayType())) {
                //  设置需要付费标识
                isNeedPaidMark = true;
            }
            //  统一处理付费情况：
            if (isNeedPaidMark) {
                //  需要付费; 除去试听，用户购买过的(专辑，声音)
                List<AlbumTrackListVo> albumTrackIdNeepListVoList = iPage.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree()).collect(Collectors.toList());
                //  远程调用：获取用户是否购买过专辑或声音Id;  如果购买过专辑：需要将专辑下对应所有的声音设置为 map.put(trackId,1);
                //  如果购买过声音：map.put(trackId,1); 没有购买过的 则设置为 map.put(trackId,0);
                List<Long> trackIdList = albumTrackIdNeepListVoList.stream().map(AlbumTrackListVo::getTrackId).collect(Collectors.toList());
                //  传递的是专辑Id，声音Id集合列表; 购买过：map.put(trackId,1); 未购买过map.put(trackId,0); 在user微服务中获取用户Id;
                Result<Map<Long, Integer>> mapResult = userInfoFeignClient.userIsPaidTrack(albumId, trackIdList);
                //  判断
                Assert.notNull(mapResult, "远程调用失败");
                Map<Long, Integer> map = mapResult.getData();
                //  循环遍历集合;
                for (AlbumTrackListVo albumTrackListVo : albumTrackIdNeepListVoList) {
                    //  最终要根据map的key来获取value; 1-albumTrackListVo.setIsShowPaidMark(false); 0-albumTrackListVo.setIsShowPaidMark(true);
                    albumTrackListVo.setIsShowPaidMark(0 == map.get(albumTrackListVo.getTrackId()));
                }
            }
        }
        //  返回数据；
        return iPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTrackInfo(Long trackId, TrackInfoVo trackInfoVo) {
        //  track_info; 获取原始声音对象数据;
        TrackInfo trackInfo = this.getById(trackId);
        String mediaFileId = trackInfo.getMediaFileId();
        //  赋值：
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        //  声音到底是否修改了? 根据流媒体Id 判断声音是否修改了.
        if (!trackInfoVo.getMediaFileId().equals(mediaFileId)) {
            //  声音被修改了.
            //  重新获取到没流体声音的最新数据;
            TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
            trackInfo.setMediaType(trackMediaInfoVo.getType());
            trackInfo.setMediaSize(trackMediaInfoVo.getSize());
            trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
            trackInfo.setMediaDuration(trackMediaInfoVo.getDuration());
            //  删除原有vod声音;
            vodService.delMediaInfo(mediaFileId);
        }
        //  修改声音对象
        this.updateById(trackInfo);
    }

    @Override
    public TrackInfo getTrackInfo(Long trackId) {
        return trackInfoMapper.selectById(trackId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeTrackInfo(Long trackId) {
        //  track_info
        TrackInfo trackInfo = this.getById(trackId);
        if (null == trackInfo) {
            //  抛出异常
            throw new RuntimeException("声音不存在");
        }
        this.trackInfoMapper.deleteById(trackId);
        //  track_stat
        trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>().eq(TrackStat::getTrackId, trackId));
        //  album_info
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
        //  赋值包含声音总数
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
        this.albumInfoMapper.updateById(albumInfo);
        //  维护当前声音的编号;
        //  update track_info set order_num = order_num - 1 where album_id = 1624 and order_num > 2 and is_deleted = 0
        trackInfoMapper.updateOrderNum(trackInfo.getAlbumId(), trackInfo.getOrderNum());
        //  vodService.delMedial();
        vodService.delMediaInfo(trackInfo.getMediaFileId());
    }

    @Override
    public IPage<TrackListVo> findUserTrackPage(Page<TrackListVo> trackListVoPage, TrackInfoQuery trackInfoQuery) {
        //  包含声音的标题，声音图片 track_info;声音统计信息:track_stat;
        return trackInfoMapper.selectUserTrackPage(trackListVoPage, trackInfoQuery);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveTrackInfo(TrackInfoVo trackInfoVo, Long userId) {
        //	track_info;
        TrackInfo trackInfo = new TrackInfo();
        //	赋值：
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        //	赋值用户Id；
        trackInfo.setUserId(userId);
        //	order_num: 表示声音的序号; order_num = include_track_count + 1
        //	select include_track_count from album_info where id = ?;
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());
        //  判断专辑对象是否为空
        if (null != albumInfo) {
            //  设置声音序号
            trackInfo.setOrderNum(albumInfo.getIncludeTrackCount() + 1);
        }
        //  根流媒体有关系;
        TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
        //  给声音对象赋值;
        trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
        trackInfo.setMediaDuration(trackMediaInfoVo.getDuration());
        trackInfo.setMediaSize(trackMediaInfoVo.getSize());
        trackInfo.setMediaType(trackMediaInfoVo.getType());
        //  保存声音对象
        trackInfoMapper.insert(trackInfo);
        //  保存声音统计数据：
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COLLECT);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COMMENT);
        //  更新专辑包含声音总数 include_track_count + 1;
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() + 1);
        this.albumInfoMapper.updateById(albumInfo);
    }

    /**
     * 保存声音统计数据
     *
     * @param trackId
     * @param statPlay
     */
    public void saveTrackStat(Long trackId, String statPlay) {
        //  创建对象
        TrackStat trackStat = new TrackStat();
        trackStat.setTrackId(trackId);
        trackStat.setStatType(statPlay);
        trackStat.setStatNum(new Random().nextInt(10000));
        trackStatMapper.insert(trackStat);
    }
}
